package com.unionftech.common.common.ui

import android.os.Bundle
import android.text.TextUtils
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.EditText
import android.widget.LinearLayout
import android.widget.TextView
import androidx.core.widget.addTextChangedListener
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.unionftech.common.R
import com.unionftech.common.R.string
import com.unionftech.common.base.mvp.annitation.InjectPresenter
import com.unionftech.common.base.mvp.impl.BaseMvpFragment
import com.unionftech.common.bean.ResponseResult
import com.unionftech.common.common.adapter.CountryFastIndexAdapter
import com.unionftech.common.common.adapter.CountrySelectAdapter
import com.unionftech.common.common.language.DynamicResourceManager
import com.unionftech.common.utils.RegexUtils
import com.unionftech.common.utils.ToastUtils
import com.unionftech.common.widget.TopLinearSmoothScroller
import com.unionftech.common.common.bean.BaseCountryInfo
import com.unionftech.common.common.bean.CountryInfo
import com.unionftech.common.common.contract.CommonContract
import com.unionftech.common.common.presenter.CommonPresenter
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.util.TreeMap


class UFCountryCodeSelectFragment : BaseMvpFragment(), CommonContract.ICountryView {
    private val mTvSelectCountryTitle: TextView by lazy { mRootView.findViewById(R.id.tv_select_country_title) }
    private val mEtSearch: EditText by lazy { mRootView.findViewById(R.id.et_search) }
    private val mLlListContainer: LinearLayout by lazy { mRootView.findViewById(R.id.ll_list_container) }
    private val mRvCountryCode: RecyclerView by lazy { mRootView.findViewById(R.id.rv_country_code) }
    private val mRvFastSearch: RecyclerView by lazy { mRootView.findViewById(R.id.rv_fast_search) }
    private val mLoadingContainer: LinearLayout by lazy { mRootView.findViewById(com.unionftech.common.R.id.loading_container) }
    private val mainScope by lazy { MainScope() }
    private val mOriginList = mutableListOf<CountryInfo>()
    private val mResultList = mutableListOf<BaseCountryInfo>()
    private val mFastCharList = mutableListOf<String>()
    private val mFastCharIndexMap = HashMap<String, Int>()
    private val mFirstCharMap = TreeMap<String, MutableList<CountryInfo>>()
    private lateinit var mCountryAdapter: CountrySelectAdapter
    private lateinit var mCountryLayoutManager: LinearLayoutManager
    private lateinit var mFastIndexAdapter: CountryFastIndexAdapter
    private var isFastScroll = false
    private var mCallBack: ((CountryInfo) -> Unit)? = null
    private val scrollListener = object : RecyclerView.OnScrollListener() {
        var state = RecyclerView.SCROLL_STATE_IDLE
        override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
            super.onScrollStateChanged(recyclerView, newState)
            state = newState
            if (state == RecyclerView.SCROLL_STATE_IDLE) {
                isFastScroll = false
            }
        }

        override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
            super.onScrolled(recyclerView, dx, dy)
            if (state == RecyclerView.SCROLL_STATE_SETTLING
                || state == RecyclerView.SCROLL_STATE_DRAGGING
            ) {
                if (!isFastScroll) {
                    val position =
                        mCountryLayoutManager.findFirstVisibleItemPosition()
                    mResultList.getOrNull(position)?.let { info ->
                        val index = mFastCharList.indexOf(info.firstChar)
                        if (index != -1) {
                            mFastIndexAdapter.setSelectIndex(index)
                        }
                    }
                }
            }
        }
    }

    @InjectPresenter
    private lateinit var mPresenter: CommonPresenter

    companion object {
        @JvmStatic
        fun newInstance() =
            UFCountryCodeSelectFragment().apply {
                arguments = Bundle().apply {
                }
            }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        arguments?.let {
        }
    }

    override fun inflaterContentView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_u_f_country_code_select, container, false)
    }

    override fun initData() {
        super.initData()
        mCountryAdapter = CountrySelectAdapter(mResultList)
        mFastIndexAdapter = CountryFastIndexAdapter(mFastCharList)
        mCountryLayoutManager = object : LinearLayoutManager(mContext, VERTICAL, false) {
            override fun smoothScrollToPosition(
                view: RecyclerView,
                state: RecyclerView.State,
                position: Int
            ) {
                val scroller = TopLinearSmoothScroller(view.context)
                scroller.targetPosition = position
                startSmoothScroll(scroller)
            }
        }
    }

    override fun initLanguageText() {
        super.initLanguageText()
        mTvSelectCountryTitle.text =
            DynamicResourceManager.getString(mContext, string.select_country_region)
        mEtSearch.hint = DynamicResourceManager.getString(mContext, string.search)
    }

    override fun setListener() {
        super.setListener()
        mCountryAdapter.setOnItemClickListener { _, _, position ->
            mResultList.getOrNull(position)?.let {
                if (it is CountryInfo) {
                    if (!TextUtils.isEmpty(it.areaCode)) {
                        mCallBack?.invoke(it)
                    }
                }
            }
        }
        mFastIndexAdapter.setOnItemClickListener { _, _, position ->
            mFastCharIndexMap[mFastCharList[position]]?.let {
                isFastScroll = true
                mFastIndexAdapter.setSelectIndex(position)
                mRvCountryCode.smoothScrollToPosition(it)
            }
        }
        mRvCountryCode.addOnScrollListener(scrollListener)

        mEtSearch.addTextChangedListener { text ->
            if (TextUtils.isEmpty(text)) {
                setOriginToPinyin(mOriginList)
            } else {
                val list = mOriginList.filter { item ->
                    val inputValue = text.toString()
                    if (RegexUtils.checkChar(inputValue)) {
                        item.nameEn.contains(inputValue, true)
                    } else {
                        item.areaCode.contains(inputValue, true)
                    }
                }
                setOriginToPinyin(list)
            }
        }
    }


    override fun setView() {
        super.setView()
        hideTitleBar()
        setupRecyclerView()
        loadData()
    }


    private fun setupRecyclerView() {
        mRvCountryCode.layoutManager = mCountryLayoutManager
        mRvCountryCode.adapter = mCountryAdapter

        mRvFastSearch.layoutManager =
            LinearLayoutManager(mContext, LinearLayoutManager.VERTICAL, false)
        mRvFastSearch.adapter = mFastIndexAdapter
    }

    override fun loadData() {
        showLoadingView()
        mPresenter.requestCountryList()
    }

    private fun showLoadingView() {
        mLoadingContainer.visibility = View.VISIBLE
        mLlListContainer.visibility = View.GONE
    }

    override fun handleCountryList(response: ResponseResult<List<CountryInfo>>) {
        hideLoadingView()
        if (response.code == ResponseResult.SUCCESS_CODE) {
            response.data?.also { list ->
                handleResponse(list)
            }
        } else {
            ToastUtils.longToast(response.msg)
        }
    }

    private fun hideLoadingView() {
        mLoadingContainer.visibility = View.GONE
        mLlListContainer.visibility = View.VISIBLE
    }

    private fun handleResponse(list: List<CountryInfo>) {
        mOriginList.clear()
        mOriginList.addAll(list)
        setOriginToPinyin(list)
    }

    private fun setOriginToPinyin(list: List<CountryInfo>) {
        mainScope.launch {
            handleCountryPinyin(list)
            mCountryAdapter.notifyDataSetChanged()
            mFastIndexAdapter.notifyDataSetChanged()
        }
    }

    override fun needShowLoading(): Boolean {
        return false
    }

    private suspend fun handleCountryPinyin(list: List<CountryInfo>) {
        withContext(Dispatchers.Default) {
            mFirstCharMap.clear()
            mFastCharList.clear()
            mResultList.clear()
            for (countryInfo in list) {
                countryInfo.isLast = false
                val nameCn = countryInfo.nameEn.replace("\n", "")
                val firstTemp = nameCn[0].uppercase()
                if (mFirstCharMap.containsKey(firstTemp)) {
                    mFirstCharMap[firstTemp]?.add(countryInfo)
                } else {
                    val infos = mutableListOf<CountryInfo>()
                    infos.add(countryInfo)
                    mFirstCharMap[firstTemp] = infos
                }
            }
            for (char in 'A'..'Z') {
                val firstChar = char.toString()
                val countryInfos = mFirstCharMap.getOrDefault(firstChar, null)
                if (!countryInfos.isNullOrEmpty()) {
                    mFastCharIndexMap[firstChar] = mResultList.size
                    val info = BaseCountryInfo()
                    info.firstChar = firstChar
                    mResultList.add(info)
                    mResultList.addAll(countryInfos)
                    //标记出本次分组的最后一个元素
                    countryInfos.getOrNull(countryInfos.size - 1)?.also {
                        it.isLast = true
                    }
                    mFastCharList.add(firstChar)
                }
            }
        }
    }

    fun setCallBack(callback: ((CountryInfo) -> Unit)?) {
        this.mCallBack = callback
    }

    override fun onDestroy() {
        mainScope.cancel()
        super.onDestroy()
    }
}